﻿using System;
using System.Collections;
using System.Diagnostics;
using System.Net;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml.XPath;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

namespace AMConvertAssistance
{
    class Program
    {
        private static string TempFolder = AppDomain.CurrentDomain.BaseDirectory + "\\amcstmp\\"; //默认文件夹用于存储查询单词
        private static string IgnoreWordsFile = AppDomain.CurrentDomain.BaseDirectory + "\\IgnoreWords.txt"; //忽略的单词列表
        private static string OutPutFile = AppDomain.CurrentDomain.BaseDirectory + "\\AMConvertAssistance_CBCYE_COM.txt";　//默认输出目录
        private static string[] ignoreWords = File.ReadAllLines(IgnoreWordsFile);
        static void Main(string[] args)
        {

            /*
            OutPutFile = QQDictContruct();
            Print("Completed");
            Console.Read();
            */

            Wellcome();

            Console.Write("请输入文本或目录地址:  ");
            string inputPath = Console.ReadLine();
            while (string.IsNullOrEmpty(inputPath))
            {
                Console.Write("请输入文本或目录地址: ");
                inputPath = Console.ReadLine();
            }
            string[] files;
            if (Path.HasExtension(inputPath))
            {
                files = new string[] { inputPath };
            }
            else
            {
                files = Directory.GetFiles(inputPath);
            }

            Print("开始执行.");
            DoWork(files);

            Console.WriteLine("程序已经执行完成,请按任意键关闭本程序并打开单词本......");
            Console.ReadLine();

            //打开文件
            Process pro = new Process();
            pro.StartInfo.FileName = "notepad.exe ";
            pro.StartInfo.Arguments = OutPutFile;
            pro.Start();
        }

        //处理方法
        static void DoWork(string[] files)
        {
            Print("读取文本内容 [开始]");
            //获取所有文本的字符串内容
            StringBuilder strBudilder = new StringBuilder();
            foreach (var file in files)
            {
                if (File.Exists(file))
                    strBudilder.Append(File.ReadAllText(file));
            }
            Print("读取文本内容 [结束]");

            Print("匹配与筛选单词 [开始]");
            Regex r = new Regex("[a-zA-Z]{2,}"); //匹配所有英文单词
            MatchCollection ms = r.Matches(strBudilder.ToString());
            ArrayList arr = new ArrayList();

            foreach (Match m in ms)
            {
                if (IsIgnoreWord(Path.GetFileNameWithoutExtension(m.Value)))
                    continue;

                if (!arr.Contains(m.Value))
                {
                    arr.Add(m.Value);
                }
            }
            Print("匹配与筛选单词 [结束]");
            Print("共查询到:" + ms.Count + " 个单词,筛选出:" + arr.Count + "个不重复的单词");

            Print("查询单词解析 [开始]");
            //string urlFormat = "http://dict.cn/ws.php?q={0}";
            string urlFormat = "http://dict.qq.com/dict?q={0}";
            if (!Directory.Exists(TempFolder))
            {
                try
                {
                    Directory.CreateDirectory(TempFolder);
                }
                catch (Exception exp)
                {
                    Print("***异常*** " + exp.Message);
                    return;
                }
            }
            for (int i = 0; i < arr.Count; i++)
            {
                if (arr[i].ToString().Length <= 2)
                    continue;

                Print("查询进度: " + i + "/" + arr.Count + " 当前单词: " + arr[i]);
                Stream remoteStream = GetRemoteStream(string.Format(urlFormat, arr[i]));
                string savedFile = TempFolder + arr[i] + ".xml";
                //StreamReader sr = new StreamReader(remoteStream, Encoding.GetEncoding("GBK"));
                StreamReader sr = new StreamReader(remoteStream, Encoding.UTF8);
                string data = sr.ReadToEnd();
                SaveToFile(savedFile, data, Encoding.UTF8);
            }
            string outPutFile;
            try
            {
                Print("查询单词解析 [结束]");

                Print("转换消息格式 [开始]");
                //outPutFile = Construct();
                outPutFile = QQDictContruct();
                Print("转换消息格式 [结束]");
            }
            catch (Exception exp)
            {
                Print("***异常*** " + exp.Message);
                return;
            }
            Print(new string('*', 50));
            Print("恭喜您!单词本生成功!");
            Print("路径: " + outPutFile);
            Print(new string('*', 50));
        }

        //构造消息
        static string Construct()
        {
            string[] files = Directory.GetFiles(TempFolder);
            StringBuilder stringBuilder = new StringBuilder();
            foreach (var file in files)
            {
                if (!File.Exists(file))
                    continue;

                XPathDocument xpathDoc = new XPathDocument(file);
                XPathNavigator xpathNav = xpathDoc.CreateNavigator();
                string questionFormat = "Q:   {0}" + Environment.NewLine; //消息格式
                string pron = xpathNav.SelectSingleNode("dict/pron") != null ? xpathNav.SelectSingleNode("dict/pron").Value : string.Empty;
                stringBuilder.Append(string.Format(questionFormat, Path.GetFileName(file).Replace(".xml", ""), pron));
                string def = xpathNav.SelectSingleNode("dict/def") != null ? xpathNav.SelectSingleNode("dict/def").Value : string.Empty;
                string orig = xpathNav.SelectSingleNode("/dict/sent[1]/orig") != null ? xpathNav.SelectSingleNode("/dict/sent[1]/orig").Value : string.Empty;
                string trans = xpathNav.SelectSingleNode("/dict/sent[1]/trans") != null ? xpathNav.SelectSingleNode("/dict/sent[1]/trans").Value : string.Empty;
                if (!string.IsNullOrEmpty(pron) && !string.IsNullOrEmpty(orig) && !string.IsNullOrEmpty(trans))
                {
                    string answerFormat = "A:   [{0}]<br/>{1}<br/><br/>[e.g.] {2}<br/>{3}" + Environment.NewLine + Environment.NewLine;
                    stringBuilder.Append(string.Format(answerFormat, pron, def, orig, trans));
                }
                else
                {
                    if (!string.IsNullOrEmpty(orig) && !string.IsNullOrEmpty(trans))
                    {
                        string answerFormat = "A:   {0}<br/><br/>[e.g.] {1}<br/>{2}" + Environment.NewLine + Environment.NewLine;
                        stringBuilder.Append(string.Format(answerFormat, def, orig, trans));
                    }
                    else
                    {
                        string answerFormat = "A:   {0}" + Environment.NewLine + Environment.NewLine;
                        stringBuilder.Append(string.Format(answerFormat, def));
                    }
                }
            }

            string content = stringBuilder.ToString();
            SaveToFile(OutPutFile, stringBuilder.ToString(), Encoding.UTF8);

            try
            {
                Directory.Delete(TempFolder, true);
            }
            catch (Exception exp)
            {
                Print("***异常*** " + exp.Message);
            }
            return OutPutFile;
        }

        static string QQDictContruct()
        {
            string[] files = Directory.GetFiles(TempFolder);
            StringBuilder stringBuilder = new StringBuilder();

            foreach (var file in files)
            {
                if (!File.Exists(file))
                    continue;

                Print("开始转换 " + Path.GetFileNameWithoutExtension(file));

                JObject Data = JObject.Parse(File.ReadAllText(file));
                CardInfo card = new CardInfo();

                try
                {
                    card.word = Data["local"][0].SelectToken("word").ToString();
                }
                catch
                {
                    continue;
                }

                try
                {
                    card.pronounce = Data["local"][0].SelectToken("pho")[0].ToString();
                }
                catch { }

                try
                {
                    JToken jDes = Data["local"][0].SelectToken("des");

                    foreach (JObject jItem in jDes)
                    {
                        if (null == jItem)
                            continue;

                        string des = string.Empty;
                        if (null != jItem["p"])
                            des += jItem["p"].ToString();

                        if (null != jItem["d"])
                            des += jItem["d"].ToString();

                        card.description += des + "<br/>";
                    }
                }
                catch { }

                try
                {
                    JToken jSen = Data["local"][0].SelectToken("sen")[0].SelectToken("s")[0];
                    string sen = string.Empty;
                    sen += "[e.g.] " + jSen["es"].ToString() + "<br/>";
                    sen += jSen["cs"].ToString() + "<br/>";
                    card.sentense = sen;
                }
                catch
                {
                }

                if (String.IsNullOrEmpty(card.description) && String.IsNullOrEmpty(card.sentense))
                    continue;

                stringBuilder.Append(makeCard(card));

                Print("结束转换 " + Path.GetFileNameWithoutExtension(file));
            }


            string content = stringBuilder.ToString();
            SaveToFile(OutPutFile, stringBuilder.ToString(), Encoding.UTF8);

            try
            {
                Directory.Delete(TempFolder, true);
            }
            catch (Exception exp)
            {
                Print("***异常*** " + exp.Message);
            }

            return OutPutFile;
        }

        //构造卡片
        static string makeCard(CardInfo card)
        {
            string strCard = string.Empty;
            string cardFormat = "Q:{0}" + Environment.NewLine + "A:{1}{2}{3}" + Environment.NewLine + Environment.NewLine;
            string pronounce = string.IsNullOrEmpty(card.pronounce) ? "" : "[" + card.pronounce + "]<br/>";
            strCard = string.Format(cardFormat, card.word, pronounce, card.description, card.sentense);
            return strCard;
        }

        //忽略单词列表
        static bool IsIgnoreWord(string word)
        {
            string regWord = "[A-D]{1,8}";
            if (Regex.IsMatch(word, regWord))
                return true;

            if (File.Exists(IgnoreWordsFile))
            {
                foreach (string item in ignoreWords)
                {
                    if (word.ToLower().Trim() == item.ToLower().Trim())
                        return true;
                }
            }
            return false;
        }


        static string savedToFile(StringBuilder stringBuilder)
        {
            string content = stringBuilder.ToString();
            SaveToFile(OutPutFile, stringBuilder.ToString(), Encoding.UTF8);

            try
            {
                Directory.Delete(TempFolder, true);
            }
            catch (Exception exp)
            {
                Print("***异常*** " + exp.Message);
            }
            return OutPutFile;
        }

        //窗口输出
        static void Print(string msg)
        {
            Console.WriteLine("[" + DateTime.Now.ToString("MM:ss") + "] " + msg);
        }

        //获取网页内容
        static Stream GetRemoteStream(string url)
        {
            string content = string.Empty;
            HttpWebResponse HttpWResp = null;
            Stream myStream = null;
            Encoding defEncoding = Encoding.UTF8;
            try
            {
                HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(url);
                myReq.Timeout = 30000;
                HttpWResp = (HttpWebResponse)myReq.GetResponse();
                myStream = HttpWResp.GetResponseStream();
                return myStream;
            }
            catch (Exception err)
            {
                Print("***异常***" + url + " " + err.Message);
            }
            Print("获取页面内容 [结束] " + url);
            return myStream;
        }

        //保存数据到文件中
        static private void SaveToFile(string savedFile, string content, Encoding encoder)
        {
            FileStream fs = new FileStream(savedFile, FileMode.Create);
            byte[] data;
            data = encoder.GetBytes(content);
            fs.Write(data, 0, data.Length);
            fs.Flush();
            fs.Close();
        }

        //介绍
        static void Wellcome()
        {
            Console.Write(@"感谢您使用AMConverter助手! v1.0
本助手可以翻译您文件中的单词并将其转换为AMConverter可识别的Txt文件。
您可以用转换之后的文件在AMConverter中转换为AnyMemo数据库，

*技巧*您可以拖拽txt文本或者单词本目录(针对多个单词本)到程序窗口,
并在确认前请点击本程序窗口，以免打开文本或目录。

祝您的英语的学习路上成功!!!
如果本程序对您有帮助,请关注我在新浪上的微博　@cbcye
作者：张城斌
Email:cbcye@live.com
http://www.cbcye.com/?p=748
感谢QQ辞典,提供单词翻译接口!

");
        }
    }

}
